package com.sokobanboxpro.game.gameplay;

import com.sokobanboxpro.game.entity.*;

/**
 * Уровень игры.
 * Один уровень может содержать пол, ящики, точки, стены и игрока
 * @author Esr
 */
public class Level {

		/**
		 * Ящики
		 */
		private Box[] boxes;
		/**
		 * Игрок
		 */
		private Player player;
		/**
		 * Точки
		 */
		private Point[] points;
		/**
		 * Стены
		 */
		private Wall[] walls;
		/**
		 * Пол
		 */
		private Floor[] floors;
		/**
		 * Ширена уровня
		 */
		private int width;
		/**
		 * Высота уровня
		 */
		private int height;

		/**
		 * Создает новый уровень
		 * @param width Ширена
		 * @param height Высота
		 * @param blocks Массив блоков, значение, которых заданы по спецификации файла уровней
		 * @throws Exception 
		 */
		public Level(int width, int height, byte[] blocks) throws Exception {

				int boxesCount = 0;
				int pointsCount = 0;
				int wallsCount = 0;
				int floorsCount = 0;

				for (int i = 0; i < blocks.length; i++) {

						switch (blocks[i]) {

								case 2:
										floorsCount++;
										break;

								case 5:
										boxesCount++;
										break;

								case 6:
										pointsCount++;
										break;

								case 1:
										wallsCount++;
										break;

								case 10:
										boxesCount++;
										pointsCount++;
										break;

								case 14:
										pointsCount++;
										break;

						}

				}

				boxes = new Box[boxesCount];
				points = new Point[pointsCount];
				walls = new Wall[wallsCount];
				floors = new Floor[floorsCount];

				boxesCount = 0;
				pointsCount = 0;
				wallsCount = 0;
				floorsCount = 0;

				if(blocks.length!=height*width)
						throw new Exception("Количество блоков не совпадает");
				for (int i = 0; i < height; i++) {
						for (int j = 0; j < width; j++) {
							
								switch (blocks[i * height + j]) {
										case 2:
												floors[floorsCount++] = new Floor(j, i);
												break;

										case 4:
												player = new Player(j, i);
												break;

										case 5:
												boxes[boxesCount++] = new Box(j, i);
												break;

										case 6:
												points[pointsCount++] = new Point(j, i);
												break;

										case 1:
												walls[wallsCount++] = new Wall(j, i);
												break;

										case 10:
												boxes[boxesCount++] = new Box(j, i);
												points[pointsCount++] = new Point(j, i);
												break;

										case 14:
												points[pointsCount++] = new Point(j, i);
												player = new Player(j, i);
												break;

								}
						}

				}

		}

		/**
		 * Получить массив ящиков
		 * @return Ящики
		 */
		public Box[] getBoxes() {
				return boxes;
		}

		/**
		 * Установить массив ящиков
		 * @param boxes Массив ящиков
		 */
		public void setBoxes(Box[] boxes) {
				this.boxes = boxes;
		}

		/**
		 * Получить игрока
		 * @return Игрок
		 */
		public Player getPlayer() {
				return player;
		}

		/**
		 * Уставноить нового игрока
		 * @param player Новый игрок
		 */
		public void setPlayer(Player player) {
				this.player = player;
		}

		/**
		 * Получить массив точек
		 * @return Массив точек
		 */
		public Point[] getPoints() {
				return points;
		}

		/**
		 * Установить массив точек
		 * @param points Массив точек
		 */
		public void setPoints(Point[] points) {
				this.points = points;
		}

		/**
		 * Получить массив стен
		 * @return Массив стен
		 */
		public Wall[] getWalls() {
				return walls;
		}

		/**
		 * Установить массив стен
		 * @param walls Массив стен
		 */
		public void setWalls(Wall[] walls) {
				this.walls = walls;
		}

		/**
		 * Получить массив пола
		 * @return Массив пола
		 */
		public Floor[] getFloors() {
				return floors;
		}

		/**
		 * Получить ширену уровня(в блоках)
		 * @return Ширена уровня
		 */
		public int getWidth() {
				return width;
		}
		
		/**
		 * Получить высоту уровня(в блоках)
		 * @return Высота уровня
		 */
		public int getHeight() {
				return height;
		}
}
